package com.dj.mingkong.portal.biz.service.music.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dj.mingkong.common.enums.StatusEnum;
import com.dj.mingkong.common.exception.ValidateException;
import com.dj.mingkong.common.infrastructure.base.dto.context.UserInfoContext;
import com.dj.mingkong.common.infrastructure.eo.database.music.BoxCollectEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.BoxEo;
import com.dj.mingkong.common.microservice.UserContext;
import com.dj.mingkong.common.util.AssertUtils;
import com.dj.mingkong.common.util.SmartBeanCopy;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxCollectAddVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxCollectCancelVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxCollectQueryVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.BoxCollectDetailVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.BoxCollectVo;
import com.dj.mingkong.portal.biz.core.base.context.UserContextHolder;
import com.dj.mingkong.portal.biz.enums.BoxTypeEnum;
import com.dj.mingkong.portal.biz.repository.database.music.BoxCollectRepository;
import com.dj.mingkong.portal.biz.repository.database.music.BoxRepository;
import com.dj.mingkong.portal.biz.service.music.BoxCollectService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Optional;

/**
 * 音乐盒管理
 *
 * @author zenglonghui
 * @date: 2023/3/23 15:37
 */
@Slf4j
@Service("boxCollectService")
public class BoxCollectServiceImpl implements BoxCollectService {
    @Resource
    private BoxRepository boxRepository;
    @Resource
    private BoxCollectRepository boxCollectRepository;
    @Resource
    private UserContextHolder userContextHolder;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void handle(BoxCollectAddVo addVo) {
        final BoxEo boxEo = this.checkBoxCollectVo(addVo);
        final Optional<BoxCollectEo> optional = boxCollectRepository
                .oneOptByUserIdAndBoxId(UserContext.getUserId(), addVo.getBoxId());
        optional.ifPresentOrElse(boxCollectEo -> {
            if (StatusEnum.VALID.equalsIntVal(boxCollectEo.getStatus())) {
                //取消收藏
                boxCollectEo.setStatus(StatusEnum.INVALID.getIntVal());
                boxRepository.updateById(boxEo.setCollectCount(boxEo.getCollectCount() - 1));
            } else {
                boxCollectEo.setStatus(StatusEnum.VALID.getIntVal());
                boxRepository.updateById(boxEo.setCollectCount(boxEo.getCollectCount() + 1));
            }
            boxCollectEo.setType(addVo.getType());
            boxCollectRepository.updateById(boxCollectEo);
        }, () -> {
            final BoxCollectEo collectEo = BoxCollectEo.builder().boxId(addVo.getBoxId())
                    .status(StatusEnum.VALID.getIntVal()).userId(UserContext.getUserId())
                    .type(addVo.getType()).build();
            boxCollectRepository.save(collectEo);
            boxRepository.updateById(boxEo.setCollectCount(boxEo.getCollectCount() + 1));
        });
    }

    @Override
    public BoxCollectDetailVo getBoxCollect(Long boxId) {
        final UserInfoContext currentUser = userContextHolder.getCurrentUser();
        if (Objects.isNull(currentUser)) {
            return BoxCollectDetailVo.builder().boxId(boxId).status(StatusEnum.INVALID.getIntVal())
                    .build();
        }
        final Optional<BoxCollectEo> optional = boxCollectRepository.oneOptByUserIdAndBoxId(currentUser.getId(), boxId);
        if (optional.isEmpty()) {
            return BoxCollectDetailVo.builder().boxId(boxId).status(StatusEnum.INVALID.getIntVal())
                    .userId(currentUser.getId()).build();
        }
        return SmartBeanCopy.copy(optional.get(), BoxCollectDetailVo.class);
    }

    @Override
    public Page<BoxCollectVo> pageByVo(BoxCollectQueryVo queryVo) {
        return boxCollectRepository.getMapper().listPage(Page.of(queryVo.getPage(), queryVo.getPageSize()), queryVo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancel(BoxCollectCancelVo cancelVo) {
        final BoxEo boxEo = boxRepository.getById(cancelVo.getBoxId());
        AssertUtils.isNotNull(boxEo, "boxId invalid");
        final Optional<BoxCollectEo> optional = boxCollectRepository
                .oneOptByUserIdAndBoxId(UserContext.getUserId(), cancelVo.getBoxId());
        optional.ifPresent(boxCollectEo -> {
            if (StatusEnum.VALID.equalsIntVal(boxCollectEo.getStatus())) {
                boxCollectEo.setStatus(StatusEnum.INVALID.getIntVal());
                boxCollectRepository.updateById(boxCollectEo);
                boxRepository.updateById(boxEo.setCollectCount(boxEo.getCollectCount() - 1));
            }
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(BoxCollectAddVo addVo) {
        final BoxEo boxEo = this.checkBoxCollectVo(addVo);
        final Optional<BoxCollectEo> optional = boxCollectRepository
                .oneOptByUserIdAndBoxId(UserContext.getUserId(), addVo.getBoxId());
        optional.ifPresentOrElse(boxCollectEo -> {
            if (StatusEnum.VALID.equalsIntVal(boxCollectEo.getStatus())) {
                throw new ValidateException("已收藏");
            }
            boxCollectEo.setStatus(StatusEnum.VALID.getIntVal());
            boxCollectEo.setType(addVo.getType());
            boxCollectRepository.updateById(boxCollectEo);
            boxRepository.updateById(boxEo.setCollectCount(boxEo.getCollectCount() + 1));
        }, () -> {
            final BoxCollectEo collectEo = BoxCollectEo.builder().boxId(addVo.getBoxId())
                    .status(StatusEnum.VALID.getIntVal()).userId(UserContext.getUserId())
                    .type(addVo.getType()).build();
            boxCollectRepository.save(collectEo);
            boxRepository.updateById(boxEo.setCollectCount(boxEo.getCollectCount() + 1));
        });
    }

    private BoxEo checkBoxCollectVo(BoxCollectAddVo boxCollectVo) {
        final BoxEo boxEo = boxRepository.getById(boxCollectVo.getBoxId());
        AssertUtils.isNotNull(boxEo, "boxEo invalid");
        if (boxEo.getUserId().equals(UserContext.getUserId())) {
            throw new ValidateException("不允许收藏本人歌单!");
        }
        if (BoxTypeEnum.DEFAULT.equalsType(boxEo.getType())) {
            throw new ValidateException("不允许收藏默认歌单!");
        }
        return boxEo;
    }

}
